consultsuggs.t

documentation
#charset "us-ascii"
#include "advlite.h"

//------------------------------------------------------------------------------------------
/*
 *   consultsuggs.t
 *
 *   Version 1.0
 *
 *   Allows a Consultable's ConsultTopics to be suggested. For the list of suggested topics to be
 *   displayed you need to give each ConsultTopic to be suggested a name and to call the
 *   Consultable's showSuggestions() method at some suitable point in your game code, for example:
 *.
 *.
 *.    blackBook: Consultable 'big black book' @startroom
 *.
 *.      readDesc()
 *.      {
 *.          "Ir's a book in which you could look up a variety of topics.<.p>";
 *.
 *.          showSuggestions();
 *.      }
 *.
 *.    ;
 *.
 *.   + ConsultTopic @tCarrots
 *.      "They're an orange root vegetable. "
 *.
 *.       name = 'carrots'
 *.   ;
 *.
 *.    + ConsultTopic @tTomatoes
 *.    "They're a round red fruit, but they're usually used as a vegetable. "
 *.
 *.       name = 'tomatoes'
 *.   ;
 *.
 *.
 *.   tCarrots: Topic 'carrots';
 *.   tTomatoes: Topic 'tomatoes';
 *
 */

/* 
 *   The Lister for listing suggested topics to THINK ABOUT. We base it on suggestedTopicLister,
 *   since most of the logic is the same.
 */
consultableSuggestionLister: suggestedTopicLister
    /* 
     *   The message to display if there are no thought topics to suggest. By default we do nothing
     *   here for suggested ConsultTopics but game code can override as required.
     */
    showListEmpty(explicit)  { }
  
    
    
    /* 
     *   Override suggestedTopicLister's list of TypeInfo to the values relevant to ConsultTopics.
     *.
     *   The first element of the list is a pointer to the list property to use on this
     *   lister object to hold the particular sublist. The second element of each list is a property
     *   pointer used to identify which sublist a ConsultTopixc belongs in, according to its own
     *   includeInList property. The third element is the type of topic entry a topic entry should
     *   be suggested as if it is explicitly requested in its suggestAs property. The fourth element
     *   is the text to use when introducing the corresponding section of the list (or nil if no
     *   introductory text is required).
     */
    typeInfo = [
        [&consultList, &consultTopics, ConsultTopic, &consultPrefix]
    ]
        
    /* Our list of ConsultTopics to suggest. This will be built by consultableSuggestionLister. */
    consultList = []   
    
    /* The text to introduce our list of suggested ConsultTopics, following "You could ". */
    consultPrefix = (source && source.customPrefix) ? source.customPrefix + ' ' : 
       BMsg(look up, 'look up ')
    
    /* 
     *   The Consultable object whose showSuggestions method has just been called to generating a
     *   suggestion list with this lister.
     */
    source = nil
;


modify Consultable
/* Display a list of topics the player can CONSULT ABOUT */
    showSuggestions()    
    {       
        /* Set up a local lst variable to hold the list of Think Abouts we want to display. */
        local lst = [];
        
        /* 
         *   Get a list of all our active thoughts whose curiosity has been aroused but not
         *   satisfied.
         */
        lst = consultTopics.subset({x: x.isActive && x.curiosityAroused && !x.curiositySatisfied});
        
        /* Reduce the list to topics the PlayerCharacter knows about */        
        lst = lst.subset({x: x.matchObj == nil || valToList(x.matchObj)[1].known});                    
           
        /* Tell our suggestion lister that we are the source of ConsultTopics to be listed. */
        mySuggestionLister.source = self;
        
        /* 
         *   Use the thoughtSuggestionLister to list the thourhs the player might want to ask about.
         */
        mySuggestionLister.show(lst);      
        
        /* 
         *   If we've just listed our suggested ConsultTopics then we're most likely going to be the
         *   Consultable the player intends to use on a subsequent turn.
         */
        currentConsultableScore = 20;
        
    }
    
    /* Carry out our Preinitialization. */
    execute()
    {
        /* Carry out our inherited Preinitialization. */
        inherited(); 
        
        /* Initialize all our ConsultTopics. */
        foreach(local t in consultList)
            t.initializeTopicEntry();
    }
    
    /* The suggestion lister to use for listing suggested ConsultTopics. */
    mySuggestionLister = consultableSuggestionLister
    
    /* 
     *   An optional custom prefix for our suggestionLister to use in place of the default, e.g.
     *   'consult the black book about '. If we define something here this must result in a valid
     *   command string when combined with the suggested ConsultTopic. e.g. 'consult the black book
     *   about carrots'. Alternatively, we can simply set useVerbosePrefix to true to generate the
     *   more verbose form 'consult the black book about' - this may be useful in situations where
     *   several Consultables may be in scope as once and we want to avoid disambiguation
     *   difficulties.
     */
    customPrefix = useVerbosePrefix ? verbosePrefix : nil    
    
    /* A more verbose form of the suggestion prefix, e.g., 'consult the black book about' */
    verbosePrefix = BMsg(verbose consult prefix, 'consult ' + theName + ' about')
    
    /* Flag, do we want this Consultable to use the more verbose prefix? By default we don't */
    useVerbosePrefix = nil  
    
;

modify ConsultTopic
    /* 
     *   A ConsultTopic should be suggested as a ConsultTopic by consultableSuggestionLister; we
     *   need to specify that here since suggestedTopicLister, from which
     *   consultableSuggestionLister inherits, needs this information.
     */
    suggestAs = ConsultTopic
    
    /* 
     *   The listOrder can be used to determine the order in which ConsultTopic suggestions are
     *   listed. Thoughts with a lower listOrder will be listed before Tboughts with a higher
     *   listOrder. By default we give all Thoughts a listOrder of 100.
     */
    listOrder = 100
    
    /* 
     *   An expression that should evaluate to true when we want this ConsultTopic to be suggested.
     *   Note that both curiosityAroused and curiositySatisfied need to be overridden by expressions
     *   or methods) in game code if something other then their default values (or true and nil
     *   respectively) are needed.
     */
    curiosityAroused = true
    
    /* 
     *   An expression that should evaluate to true when we no lomger want this ConsultTopic to be
     *   suggested. This needs to be overriden by game code if desired; the extension makes no
     *   attempt to update curiositySatisifed to true when, say, a Thought topic has been suggested
     *   once or so many times, as each game will probably want to handle this in a different way.
     */
    curiositySatisfied = nil
    
    /* 
     *   The name to be displayed if you want this Thought to be suggested in response to a THINK
     *   command. This should be something that would match the vocab of the Topic associated with
     *   this Thought. Alternatively, autoName can be set to true to have the name set to the name
     *   of the Topic (or Thing) this Thought matches.
     */
    name = nil
    
    
    /* 
     *   If autoName is true, the library will attempt to define the name property from our
     *   associated Topic, provided name hasn't already been defined.
     */
    autoName = nil
    
    
    /* Initialize this ConsultTopic (this is actually called at preinit) */
    initializeTopicEntry()
    {            
        inherited();
        
        /*  
         *   If our autoname property is true, construct our name (for use in
         *   suggesting this TopicEntry) provided we have something to construct
         *   it from.
         */
        if(autoName && matchObj != nil && name is in (nil, ''))
            buildName();
    }
    
    
     /* 
     *   Construct the name of this ActorTopicEntry by using the theName
     *   property of our first matchObj.     
     */
    buildName() { name = valToList(matchObj)[1].theName; }
;


/* 
 *   A PreParsr that traps numerical input (e.g. a command consisting purely of an integer, such as
 *   2), and translates it into the THINK ABOUT command in the latest list of enumerated thought
 *   suggesstions.
 */ 

enumConsultableSuggestionsPreparser: StringPreParser
    doParsing(str, which)   
    {
        /* 
         *   We only want to modify str here if this is a new command 
         *   suggestedTopicLister's enumerateSuggestions property is set to true.
         */
        if(which == rmcCommand && consultableSuggestionLister.enumerateSuggestions)
        {
            /* Try converting str to an integer */
            local num = toInteger(str);
            
            /* 
             *   If we have a number and that number is in the range of the number of topic
             *   suggestions listed then replace str with the corresponding conversational command.
             */
            if(num && num <= suggestionEnumerator.count && num > 0)
            {
                /* 
                 *   Change str to the corresponding item in suggestionEnumerator's suggestion list.
                 */
                str = suggestionEnumerator.suggestionList[num];
                
                /* 
                 *   Echo the new command back to the player so the player can see what's now being
                 *   executed.
                 */
                "<.inputline>\^<<str>><./inputline>\n";
            }            
        }       
        
        /* Return our string, modified or unmodified as the case may be. */
        return str;
    }    
;

Adv3Lite Library Reference Manual
Generated on 13/06/2025 from adv3Lite version 2.2.1